/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.unicam.fishpass.prism;

/**
 * evaluates the boolean expressions
 * 
 * @author Andrea Baiocco
 */
public class BooleanExpression {

	private ArithmeticExpression aLeft;
	private ArithmeticExpression aRight;
	private BooleanExpression bLeft;
	private BooleanExpression bRight;
	private int operator;
	private boolean bool;
	private String var = null;

	/**
	 * @param left
	 * @param right
	 * @param operator
	 */
	public BooleanExpression(ArithmeticExpression left,
			ArithmeticExpression right, int operator) {
		this.aLeft = left;
		this.aRight = right;
		bLeft = null;
		bRight = null;
		this.operator = operator;
	}

	/**
	 * @param right
	 * @param operator
	 */
	public BooleanExpression(BooleanExpression right, int operator) {
		this.bRight = right;
		bLeft = null;
		aLeft = null;
		aRight = null;
		this.operator = operator;
	}

	/**
	 * @param left
	 * @param right
	 */
	public BooleanExpression(BooleanExpression left, BooleanExpression right) {
		this.bLeft = left;
		this.bRight = right;
		aLeft = null;
		aRight = null;
		operator = -1;
	}

	/**
	 * @param bool
	 */
	public BooleanExpression(boolean bool) {
		this.bool = bool;
		aLeft = null;
		aRight = null;
		bLeft = null;
		bRight = null;
		operator = -1;
	}

	public BooleanExpression(String var) {
		this.var = var;
		aLeft = null;
		aRight = null;
		bLeft = null;
		bRight = null;
		operator = -1;
	}

	boolean evaluateExpression(Declaration[] decs, int[] clocks, float[] vars) {
		// it is not a compound expression or a not expression (! BEXPR)
		if ((bLeft == null && bRight == null)
				&& (aLeft == null && aRight == null)
				&& operator != Constant.NOT) {
			return bool;
		}
		// if it is a compound boolean...
		if (bLeft != null && bRight != null) {
			return bLeft.evaluateExpression(decs, clocks, vars)
					&& bRight.evaluateExpression(decs, clocks, vars);
		}
		// if it is just a variable
		if (var != null)
			return Utility.getBoolValue(var, decs, clocks, vars);

		// if it is a NOT expression (right is "null")
		if (bRight != null && bLeft == null) {
			return !bRight.evaluateExpression(decs, clocks, vars);
		}
		// else it is an arithmetic expression...
		int valueL = aLeft.calculateExpression();
		int valueR = aRight.calculateExpression();
		//
		switch (operator) {
		case (Constant.EQ): // =
			return valueL == valueR;
		case (Constant.LEQ): // <=
			return valueL <= valueR;
		case (Constant.LS): // <
			return valueL < valueR;
		case (Constant.GR): // >
			return valueL > valueR;
		case (Constant.GEQ): // >=
			return valueL >= valueR;
		}
		return false;
	}

	@Override
	public String toString() {
		if ((bLeft == null && bRight == null)
				&& (aLeft == null && aRight == null)
				&& operator != Constant.NOT) {
			return Boolean.toString(bool);
		}
		// if it is a compound boolean...
		if (bLeft != null && bRight != null) {
			return "(" + bLeft.toString() + operator + bRight.toString() + ")";
		}
		// if it is a NOT expression (left is "null")
		if (bRight != null && bLeft == null) {
			return "!" + bRight.toString();
		}
		// if it is just a boolean expression
		if (var != null)
			return Utility.getBoolValue(var, null, null, null) ? "true"
					: "false";
		// else it is an arithmetic expression...
		return "(" + aLeft.toString() + operator + aRight.toString() + ")";
	}

}
